package mobile.game.core.config;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import mobile.game.core.support.Utils;

import java.util.Properties;
import java.util.Set;

/**
 * @author gaopan
 *
 * jowDistr.properties
 */
public class JowDistr {
	/** 配置文件名称 */
	private static final String CONFIG_NAME = "jowDistr.properties";
	
	//-----------------------------------------------------------------------
	// 跨服设置
	
	/** 是否是跨服服务器 */
	public static final boolean CROSS_IS;
	/** 跨服服务器id */
	public static final int CROSS_SERVER_ID;
	/** 跨服服务器平台id */
	public static final int CROSS_PLATFORM_ID;
	/** 跨服服务器ip */
	public static final String CROSS_IP;
	/** 跨服服务器的连接服务器端口 */
	public static final int CROSS_PORT;
	
	//-----------------------------------------------------------------------
	// SDK相关
	
	/** 内部Platform的http服务ip地址 */
	public static final String HTTP_IP;
	/** 内部Platform的http服务port */
	public static final int HTTP_PORT;
	/** http会话密钥 */
	public static final String HTTP_SESSION_KEY;
	/** 内部Platform的http服务允许接收的IP */
	public static List<String> HTTP_ACCEPT_IP_LIST;
	
	/** 外部GM服务器ip */
	public static final String HTTP_GM_IP;
	/** 外部GM服务器port */
	public static final int HTTP_GM_PORT;
	
	/** 外部充值服务器ip */
	public static final String HTTP_CHARGE_IP;
	/** 外部充值记录上传服务器 */
	public static final String HTTP_CHARGE_RECORED_UPLOAD;
	
	//-----------------------------------------------------------------------
	// 其他
	
	/** 最大在线人数 */
	public static final int LOGIN_MAX_ONLINE;
	/** 服务器间通信密钥 */
	public static final String GAME_SECRET_KEY;
	
	//-----------------------------------------------------------------------
	// 分布式服务器配置
	
	/** 游戏服务实例数 */
	public static final int NODE_WORLD_STARTUP_NUM;
	
	/** 数据分配服务实例数 */
	public static final int PORT_STARTUP_NUM_DB_PART;
	/** 数据执行服务实例数 */
	public static final int PORT_STARTUP_NUM_DB_LINE;
	/** 连接服务实例数 */
	public static final int PORT_STARTUP_NUM_CONN;
	/** 验证服务实例数 */
	public static final int PORT_STARTUP_NUM_LOGIN;				
	/** 验证服务实例数 */
	public static final int PORT_STARTUP_NUM_HTTP;	
	/** 验证服务实例数 */
	public static final int PORT_STARTUP_NUM_GIFT;	
	/** 地图Port服务实例数 */
	public static final int PORT_STAGE_STARTUP_NUM;
	/** 游戏业务Port服务实例数 */
	public static final int PORT_GAME_STARTUP_NUM;
	
	/** dbsrv */
	/** Node */
	/** 数据库Node名称 */
	private static final String NODE_DB = "db";
	/** Port */
	/** 数据分配Port前缀 */
	public static final String PORT_DB_PART_PREFIX = "dbPart";
	/** 数据执行Port前缀 */
	public static final String PORT_DB_LINE_PREFIX = "dbLine";
	/** ID分配Port */
	public static final String PORT_ID_ALLOT = "idAllot";
	/** ID分配服务 */
	public static final String SERV_ID_ALLOT = "idAllot";
	
	/** connsrv */
	/** 连接服务器Node前缀 */
	private static final String NODE_CONN_PREFIX = "conn";
	/** 连接服务器port前缀 */
	public static final String PORT_CONN_PREFIX = "conn";
	/** 连接总服务 */
	public static final String SERV_CONN = "conn";
	
	/** platform */
	private static final String NODE_PLATFORM = "platform";
	/** 前缀 */
	/** 登陆服务Port前缀 */
	public static final String PORT_LOGIN_PREFIX = "login";
	/** HTTP服务Port前缀 */
	public static final String PORT_HTTP_PREFIX = "http";
	/** Gift服务Port前缀 */
	public static final String PORT_GIFT_PREFIX = "gift";

	/** 服务 */
	/** 登陆服务ID */
	public static final String SERV_LOGIN = "login";
	/** 对平台服务器提供服务 */
	public static final String SERV_GIFT = "gift";
	
	/** worldsrv */
	/** 游戏服务器Node前缀 */
	private static final String NODE_WORLD_PREFIX = "world";
	/** 默认主控游戏服务Node */
//	public static final String NODE_DEFAULT = "world0";
	/** 默认主控游戏服务Port */
	public static final String PORT_DEFAULT = "port0";
	/** 默认主控游戏服务Serv */
	public static final String SERV_DEFAULT = "serv0";
	/** 选人服务 */
	public static final String SERV_GATE = "gate";
	/** 对平台服务器提供服务 */
	public static final String SERV_WORLD_PF = "worldPF";
	/** 运行信息统计服务 */
	public static final String SERV_STATISTICS = "statistics";

	/** 用于逻辑服和跨服之间的数据接收和发送 */
	public static final String PORT_ENTREPOT = "entrepot";
	/** 用于逻辑服和跨服之间的数据接收和发送 */
	public static final String SERV_ENTREPOT = "entrepot";
	
	/** 游戏业务Port前缀 */
	public static final String PORT_GAME_PREFIX = "game";
	/** 游戏地图Port前缀 */
	public static final String PORT_STAGE_PREFIX = "stage";
	
	/** 服务 */
	public static final String SERV_TEST = "test";
	/** 玩家创建申请服务 */
	public static final String SERV_HUMAN_CREATE_APPLY = "humanCreateApply";
	/** 全局地图信息服务 */
	public static final String SERV_STAGE_GLOBAL = "stageGlobal";
	/** 全局玩家信息服务 */
	public static final String SERV_HUMAN_GLOBAL = "humanGlobal";
	/** 每日数据重置 */
	public static final String SERV_DATA_RESET = "dataReset";
	/** 地图默认服务 */
	public static final String SERV_STAGE_DEFAULT = "stageDefault";
	/** 邮件服务 */
	public static final String SERV_MAIL = "mail";
	/** 待办服务 */
	public static final String SERV_POCKETLINE = "pocketLine";
	/** 排行服务 */
	public static final String SERV_RANK = "rank";
	/** 军团服务 */
	public static final String SERV_UNION = "union";
	/** 活动 */
	public static final String SERV_ACTIVITY = "activity";
	/** 名字服务 */
	public static final String SERV_NAME = "name";
	/** 组队服务 */
	public static final String SERV_TEAM = "team";
	/** 组队匹配服务 */
	public static final String SERV_TEAM_MATCH = "teamMatch";
	/** 好友服务 */
	public static final String SERV_FRIEND = "friend";
	/** 全部玩家摘要信息 */
	public static final String SERV_HUMAN_DIGEST = "humanDigest";
	/** 资源加载 */
	public static final String SERV_CROSS = "cross";
	/** 世界BOSS */
	public static final String SERV_WORLDBOSS = "worldBoss";
	/**  红包 */
	public static final String SERV_REDPACKET = "redPacket";
	/** 排位赛 */
	public static final String SERV_QUALIFYING = "qualifying";
	/** 交易行 */
	public static final String SERV_TRADE = "trade";
	
	/** 配置前缀 */
	private static final String PREFIX_NODE_ADDR = "node.addr";
	private static final String PREFIX_CROSS_ADDR = "cross.addr";
	private static final String PREFIX_PORT_STARTUP = "port.startwith";
	private static final String PREFIX_SERV_STARTUP = "serv.startwith";
	
	/** nodeId -> node addr */
	private static final Map<String, String> NODE_ADDR = new HashMap<>();
	/** portId -> nodeId */
	private static final Map<String, String> PORT_STARTWITH = new HashMap<>();
	/** servId -> portId */
	private static final Map<String, String> SERV_STARTWITH = new HashMap<>();
	/** 所有连接的逻辑服nodeId */
	private static final Set<String> CROSS_NODES = new HashSet<String>();
	
	static {
		// 获取配置
		Properties prop = Utils.readProperties(CONFIG_NAME);
		
		CROSS_IS = Utils.booleanValue(prop.getProperty("cross.is"));
		CROSS_SERVER_ID = Utils.intValue(prop.getProperty("cross.server.id"));
		CROSS_PLATFORM_ID = Utils.intValue(prop.getProperty("cross.platform.id"));
		CROSS_IP = prop.getProperty("cross.ip");
		CROSS_PORT = Utils.intValue(prop.getProperty("cross.port"));
		
		HTTP_IP = prop.getProperty("http.ip");
		HTTP_PORT = Utils.intValue(prop.getProperty("http.port"));
		HTTP_SESSION_KEY = prop.getProperty("http.session.key");
		HTTP_ACCEPT_IP_LIST = new ArrayList<>();
		for(int i = 1; i < 100; ++i) {
			String ip = prop.getProperty("http.accept.ip" + i);
			if(ip == null) {
				continue;
			}
			
			HTTP_ACCEPT_IP_LIST.add(ip);
		}
		
		HTTP_GM_IP = prop.getProperty("http.gm.ip");
		HTTP_ACCEPT_IP_LIST.add(HTTP_GM_IP);
		HTTP_GM_PORT = Utils.intValue(prop.getProperty("http.gm.port"));
		HTTP_CHARGE_IP = prop.getProperty("http.charge.ip");
		HTTP_ACCEPT_IP_LIST.add(HTTP_CHARGE_IP);
		HTTP_CHARGE_RECORED_UPLOAD = prop.getProperty("http.charge.record.upload");
		
		LOGIN_MAX_ONLINE = Utils.intValue(prop.getProperty("login.max.online"));
		GAME_SECRET_KEY = prop.getProperty("game.secret.key");
		
		NODE_WORLD_STARTUP_NUM = Integer.valueOf(prop.getProperty("node.startup.num.world"));
		PORT_STARTUP_NUM_DB_PART = Utils.intValue(prop.getProperty("port.startup.num.dbPart"));
		PORT_STARTUP_NUM_DB_LINE = Utils.intValue(prop.getProperty("port.startup.num.dbLine"));
		PORT_STARTUP_NUM_CONN = Utils.intValue(prop.getProperty("port.startup.num.conn"));
		PORT_STARTUP_NUM_LOGIN = Utils.intValue(prop.getProperty("port.startup.num.login"));
		PORT_STARTUP_NUM_HTTP = Utils.intValue(prop.getProperty("port.startup.num.http"));
		PORT_STARTUP_NUM_GIFT = Utils.intValue(prop.getProperty("port.startup.num.gift"));
		PORT_STAGE_STARTUP_NUM = Integer.valueOf(prop.getProperty("port.startup.num.stage"));
		PORT_GAME_STARTUP_NUM = Integer.valueOf(prop.getProperty("port.startup.num.game"));
		
		// 分布式服务器配置
		for(Entry<Object, Object> e : prop.entrySet()) {
			// 配置的值
			String pk = (String) e.getKey();
			String pv = (String) e.getValue();
			
			// 分解Key为前缀和关键字
			int lastIndexPoint = pk.lastIndexOf(".");
			String prefix = pk.substring(0, lastIndexPoint);
			String key = pk.substring(lastIndexPoint + 1);

			// Node地址配置
			if(PREFIX_NODE_ADDR.equals(prefix)) {
				String nodeId = key + "_" + JowConfig.GAME_SERVER_ID + "_" + JowConfig.GAME_PLATFORM_ID;
				NODE_ADDR.put(nodeId, pv);
			
			// Port启动配置
			} else if(PREFIX_PORT_STARTUP.equals(prefix)) {
				String nodeId = pv + "_" + JowConfig.GAME_SERVER_ID + "_" + JowConfig.GAME_PLATFORM_ID;
				PORT_STARTWITH.put(key, nodeId);
			
			// Service启动配置
			} else if(PREFIX_SERV_STARTUP.equals(prefix)) {
				SERV_STARTWITH.put(key, pv);
			
			// 跨服Node地址配置
			} else if (PREFIX_CROSS_ADDR.equals(prefix)) {
				NODE_ADDR.put(key, pv);
				CROSS_NODES.add(key);
			}
		}
	}
	
	/**
	 * 获取Node连接地址
	 * @param nodeId
	 * @return
	 */
	public static String getNodeAddr(String nodeId) {
		return NODE_ADDR.get(nodeId);
	}
	
	/**
	 * 通过Port来获取父节点Node
	 * @param portId
	 * @return
	 */
	public static String getNodeId(String portId) {
		return PORT_STARTWITH.get(portId);
	}
	
	/**
	 * 通过Serv来获取父节点Port
	 * @param servId
	 * @return
	 */
	public static String getPortId(String servId) {
		return SERV_STARTWITH.get(servId);
	}
	
	/**
	 * 获取默认主控游戏服务NodeId
	 * @return
	 */
	public static String getDefaultNodeId() {
		return getWorldNodeId(0);
	}
	
	/**
	 * 通过index来获取World Node
	 * @param index
	 * @return
	 */
	public static String getWorldNodeId(int index) {
		return NODE_WORLD_PREFIX + index + "_" + JowConfig.GAME_SERVER_ID + "_" + JowConfig.GAME_PLATFORM_ID;
	}
	
	/**
	 * 获取DB Node
	 * @return
	 */
	public static String getDBNodeId() {
		return NODE_DB + "_" + JowConfig.GAME_SERVER_ID + "_" + JowConfig.GAME_PLATFORM_ID;
	}
	
	/**
	 * 通过index获取Conn Node
	 * @param index
	 * @return
	 */
	public static String getConnNodeId(int index) {
		return NODE_CONN_PREFIX + index + "_" + JowConfig.GAME_SERVER_ID + "_" + JowConfig.GAME_PLATFORM_ID;
	}
	
	/**
	 * 获取Platform Node
	 * @return
	 */
	public static String getPlatformNodeId() {
		return NODE_PLATFORM + "_" + JowConfig.GAME_SERVER_ID + "_" + JowConfig.GAME_PLATFORM_ID;
	}
	
	/**
	 * 获取远程nodeId
	 * 
	 * @param serverId
	 * @param platformId
	 * @return
	 */
	public static String getRemoteNodeId(int serverId, int platformId) {
		return NODE_WORLD_PREFIX + "0_" + serverId + "_" + platformId;
	}
	
	/**
	 * 获取跨服nodeId
	 * 
	 * @return
	 */
	public static String getCrossNodeId() {
		return NODE_WORLD_PREFIX + "0_" + CROSS_SERVER_ID + "_" + CROSS_PLATFORM_ID;
	}
	
	/**
	 * 获取所有中转的远程nodeId
	 * 
	 * @return
	 */
	public static Set<String> getEntrepotNodeId() {
		return CROSS_NODES;
	}
	
	/**
	 * 确定分配执行线程的PortId
	 * @param tableName
	 * @param id
	 * @return
	 */
	public static String linePortId(String tableName, long id) {
		long hash = tableName.hashCode() + Math.max(id, 0);
		hash = Utils.hash((int)hash);
		
		if(hash < 0) hash = Math.abs(hash);
		
		return PORT_DB_LINE_PREFIX + (hash % PORT_STARTUP_NUM_DB_LINE);
	}
}
